package liuyang.bigeventserver.modules.security.jwt.impl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import liuyang.bigeventserver.modules.security.jwt.JwtTokenService;
import liuyang.bigeventserver.modules.security.jwt.JwtTokenServiceProperties;
import liuyang.bigeventserver.modules.security.jwt.vo.PrincipalInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.Date;

/**
 * @author xconf
 * @since 2024/3/1
 */
@Service
@Slf4j
public class Auth0TokenService implements JwtTokenService {

    private final JwtTokenServiceProperties jwtTokenServiceProperties;
    private Algorithm algorithm;

    public Auth0TokenService(JwtTokenServiceProperties jwtTokenServiceProperties) {
        this.jwtTokenServiceProperties = jwtTokenServiceProperties;
        this.algorithm = Algorithm.HMAC256(jwtTokenServiceProperties.getSecretKey());
    }

    @Override
    public String getSecretKey() {
        return jwtTokenServiceProperties.getSecretKey();
    }

    @Override
    public String getIssuer() {
        return jwtTokenServiceProperties.getIssuer();
    }

    @Override
    public Long getTtl() {
        return jwtTokenServiceProperties.getTtl();
    }

    @Override
    public String sign(String username) {
        return sign(username, username);
    }

    @Override
    public String sign(String userid, String username) {
        final String token = JWT.create()
                //.withJWTId(jti)// 保留为JWT自己使用
                .withClaim("userid", userid)// 业务相关的userid
                .withSubject(username)
                .withIssuer(jwtTokenServiceProperties.getIssuer())
                .withExpiresAt(new Date(System.currentTimeMillis() + jwtTokenServiceProperties.getTtl()))
                .sign(algorithm);
        log.debug("jwt = {}", token);
        return token;
    }


    @Override
    public PrincipalInfo verify(String token) {
        PrincipalInfo info = new PrincipalInfo();
        final DecodedJWT decodedJWT = JWT.require(algorithm).build().verify(token);
        info.setId((decodedJWT.getClaim("userid").asString()));// userid
        info.setSubject(decodedJWT.getSubject());// username
        return info;
    }
}
